/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.service.core.impl;

import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.model.core.ContentField;
import com.blandware.atleap.model.core.ContentFieldValue;
import com.blandware.atleap.model.core.ContentLocale;
import com.blandware.atleap.persistence.core.ContentFieldDAO;
import com.blandware.atleap.persistence.core.ContentFieldValueDAO;
import com.blandware.atleap.persistence.core.ContentLocaleDAO;
import com.blandware.atleap.persistence.exception.DeleteException;
import com.blandware.atleap.service.core.ContentLocaleManager;
import com.blandware.atleap.service.exception.BeanAlreadyExistsException;
import com.blandware.atleap.service.exception.BeanNotFoundException;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.ListIterator;

/**
 * <p>Implementation of ContentLocaleManager</p>
 * <p><a href="ContentLocaleManagerImpl.java.html"><i>View Source</i></a>
 * </p>
 * <p/>
 *
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.24 $ $Date: 2007/12/11 14:23:44 $
 */
public class ContentLocaleManagerImpl extends BaseManagerImpl implements ContentLocaleManager {

    /**
     * Content locale DAO
     */
	protected ContentLocaleDAO contentLocaleDAO;

    /**
     * Content field DAO
     */
	protected ContentFieldDAO contentFieldDAO;

    /**
     * Content field value DAO
     */
	protected ContentFieldValueDAO contentFieldValueDAO;

	/**
	 * List of all locales, available in the system
	 */
	protected List availableLocales;

    /**
     * List of all enabled locales
     */
    protected List enabledLocales;

    /**
	 * List of active locales
	 */
	protected List activeLocales;

	/**
	 * Default locale
	 */
	protected ContentLocale defaultLocale;

	/**
	 * Creates new instance of ContentLocaleManagerImpl
	 */
	public ContentLocaleManagerImpl() {
	}

    /**
     * Sets DAO for operating with content locales
     *
     * @param contentLocaleDAO the DAO to set
     */
	public void setContentLocaleDAO(ContentLocaleDAO contentLocaleDAO) {
		this.contentLocaleDAO = contentLocaleDAO;
	}

    /**
     * Sets DAO for operating with content fields
     *
     * @param contentFieldDAO the DAO to set
     */
	public void setContentFieldDAO(ContentFieldDAO contentFieldDAO) {
		this.contentFieldDAO = contentFieldDAO;
	}

    /**
     * Sets DAO for operating with content field values
     *
     * @param contentFieldValueDAO the DAO to set
     */
	public void setContentFieldValueDAO(ContentFieldValueDAO contentFieldValueDAO) {
		this.contentFieldValueDAO = contentFieldValueDAO;
	}


	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#initialize()
	 */
    public void initialize() {
	    doCache();
        if (log.isInfoEnabled()) {
            log.info("Content locales initialized");
        }
    }

	/**
	 * Caches available locales, active locales and default one
	 */
	protected void doCache() {
		// get list of locales
		availableLocales = listContentLocales(null).asList();

		// get enabled, active locales and set default one
        enabledLocales = new ArrayList();
        activeLocales = new ArrayList();
		for ( ListIterator i = availableLocales.listIterator(); i.hasNext(); ) {
			ContentLocale locale = ((ContentLocale) i.next()).shallowCopy();
            if (locale.isEnabled()) {
                enabledLocales.add(locale);
                if ( locale.isActive() ) {
                    activeLocales.add(locale);
                    if ( locale.getDefaultInstance().booleanValue() ) {
                        defaultLocale = locale;
                    }
                }
            }
            i.set(locale);
		}
        // TODO: If no default locale present in system (the DB is corrupted for instance), default locale will contain something wrong. Fix it
	}

	//~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#createContentLocale(com.blandware.atleap.model.core.ContentLocale)
	 */
	public void createContentLocale(ContentLocale contentLocale) throws BeanAlreadyExistsException {

		if ( log.isDebugEnabled() ) {
			log.debug("Creating new content locale (identifier=" + contentLocale.getIdentifier() + ")...");
		}

		ContentLocale existingContentLocale = contentLocaleDAO.retrieveContentLocale(contentLocale.getIdentifier());
		if ( existingContentLocale != null ) {
			// locale already exists
			String errorMessage = "Content locale with identifier '" + contentLocale.getIdentifier() + "' already exists";
			if ( log.isErrorEnabled() ) {
				log.error(errorMessage);
			}
			throw new BeanAlreadyExistsException(errorMessage);
		}

		Integer localesCount = contentLocaleDAO.listContentLocales(null).getTotal();
		if ( localesCount.intValue() == 0 ) {
			contentLocale.setDefaultInstance(Boolean.TRUE);
			contentLocale.setActive(Boolean.TRUE);
		} else {
			contentLocale.setDefaultInstance(Boolean.FALSE);
			contentLocale.setActive(Boolean.FALSE);
		}

        // TODO: solve problem with hardcoded items when there is no content locale in system (we're creating the first one)

		// locale does not exist, so create it
		contentLocaleDAO.createContentLocale(contentLocale);

		// create empty CFV with current locale for all content fields
		List contentFields = contentFieldDAO.listContentFields(null).asList();
		for ( Iterator i = contentFields.iterator(); i.hasNext(); ) {
			ContentField contentField = (ContentField) i.next();
			ContentFieldValue contentFieldValue = new ContentFieldValue();
			if ( contentField.getType() == ContentField.LINE_TYPE ) {
				contentFieldValue.setSimpleValue("");
			} else {
				contentFieldValue.setValue(new byte[0]);
			}
			contentFieldValueDAO.createContentFieldValue(contentFieldValue, contentField, contentLocale);
		}

		doCache();

		if ( log.isDebugEnabled() ) {
			log.debug("New locale has been created successfully.");
		}

	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#retrieveContentLocale(java.lang.String)
	 */
	public ContentLocale retrieveContentLocale(String localeIdentifier) {
		ContentLocale contentLocale;
		contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);
		return contentLocale;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#updateContentLocale(com.blandware.atleap.model.core.ContentLocale)
	 */
	public void updateContentLocale(ContentLocale contentLocale) {
        // remove content locale from cache in order to prevent Hibernate from assigning new version number
		contentLocaleDAO.removeFromCache(contentLocale);

		if ( log.isDebugEnabled() ) {
			log.debug("Updating content locale (identifier=" + contentLocale.getIdentifier() + ")...");
		}

		contentLocaleDAO.updateContentLocale(contentLocale);

		doCache();

		if ( log.isDebugEnabled() ) {
			log.debug("Locale was updated succefully.");
		}
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#deleteContentLocale(java.lang.String)
	 */
	public void deleteContentLocale(String localeIdentifier) throws DeleteException, BeanNotFoundException {

		if ( log.isDebugEnabled() ) {
			log.debug("Deleting locale with identifier '" + localeIdentifier + "'");
		}

		ContentLocale contentLocale = contentLocaleDAO.retrieveContentLocale(localeIdentifier);
		if ( contentLocale == null ) {
			String errorMessage = "No locale with identifier=" + localeIdentifier + "could be found";
			throw new BeanNotFoundException(errorMessage);
		}

		if ( contentLocale.getDefaultInstance().booleanValue() ) {
			throw new DeleteException("Content locale is default and cannot be deleted.");
		}

		contentLocaleDAO.deleteContentLocale(contentLocale);

		doCache();

		if ( log.isDebugEnabled() ) {
			log.debug("Locale has been deleted successfully");
		}
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#listContentLocales(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentLocales(QueryInfo queryInfo) {
		return contentLocaleDAO.listContentLocales(queryInfo);
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#getAvailableLocales()
	 */
	public List getAvailableLocales() {
		return availableLocales;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#getEnabledLocales()
	 */
	public List getEnabledLocales() {
		return enabledLocales;
	}

    /**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#getActiveLocales()
	 */
	public List getActiveLocales() {
		return activeLocales;
	}

	/**
	 * @see com.blandware.atleap.service.core.ContentLocaleManager#getDefaultLocale()
	 */
	public ContentLocale getDefaultLocale() {
		return defaultLocale;
	}

	// ~ Finders ================================================================

	// ~ Service methods ================================================================

}
